#[macro_use]
mod macros_func;

use crate::IP::{IPV4, IPV6};
use std::borrow::BorrowMut;
use std::cell::{Cell, Ref, RefCell};
use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Display};
use std::fs::File;
use std::io::stdin;
use std::mem::replace;
use std::ops::{Add, Deref, DerefMut, Div, Mul, Rem, Sub};
use std::rc::Rc;
use std::sync::{mpsc, Mutex};
use std::thread;
use std::time::Duration;

mod list;
mod list2;
mod thread_pool;
mod type_rust;

use crate::list::ForwardList;
use macros_func::testFn;

#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}
#[derive(PartialEq, Debug)]
enum IP {
    IPV4,
    IPV6,
}

fn test_ip(ip: &IP) {
    if *ip == IP::IPV4 {
        DBG!(IP::IPV4);
    } else {
        DBG!(IP::IPV6);
    }
}
fn test_slice_str(intro: &str, head: usize, tail: usize) -> &str {
    if head > 0 || tail < intro.len() {
        return &intro[head..tail];
    }
    return &intro[..];
}

fn test_slice_string(intro: &str, head: usize, tail: usize) -> String {
    if head > 0 || tail < intro.len() {
        return String::from(&intro[head..tail]);
    }
    return String::from(&intro[..]);
}

fn test_slice_cstring(intro: &str, head: usize, tail: usize) -> String {
    if head > 0 || tail < intro.len() {
        let mut result = String::new();
        for i in [head..tail] {
            result.push_str(&intro[i]);
        }
        return result;
    }
    "".to_string()
}
async fn testAsy() {
    println!("asdasd");
}

fn main() {
    futures::executor::block_on(testAsy());

    let mut list = ForwardList::new();
    for i in 0..=10 {
        list.push_head(i);
    }
    let mut no = No {
        name: String::from("asd"),
    };
    let mn = &mut no;
    let option = &Some(mn);

    let opr1 = option;

    let opr2 = option;
    if let Some(x) = opr1 {
        unsafe {
            let x2 = (*x) as *const No as *mut No;
            (&mut *x2).name = "ad".to_string();
        }
    }

    fn testOption(op: &mut Option<&mut No>) {
        if let Some(x) = op {
            x.name = "ad".to_string();
        }
    }
    let mut no1 = &mut No {
        name: "asd".to_string(),
    };
    #[derive(Debug, Default)]
    struct No {
        name: String,
    }

    impl No {
        // T &T &mut T
        // 引用类似于给T套上一层无形的壳，& &mut决定壳中变量可变属性
        // 可变性自上向下层层限制
        fn s1(self) {
            // 允许T,mut T
            /*T 没有实现clone+copy*/
            //获取T 所有权，调用时入参变量将失去所有权
            // 一般用于“consumer“操作, 打印，转换所有权为其他类型

            /*T 没有实现clone+copy*/
            //获取T拷贝所有权，调用时入参依旧可以使用
            //注意T<&>类型，如果是不变&是安全的，如果是T<&mut>是不安全的，会出现double &mut

            //因为进入此方法后所有权都属于self变量，可以随意处理
            //mut T : 允许T更改，T中的内容更改
            //ref T : 允许&T
            //ref mut T : 允许&mut T 以上类似于语法糖
        }
        fn s2(&self) {
            //允许T,&T,&mut T,其中T会默认添加& T.fn() => T::fn(&t)
        }
        fn s3(&mut self) {
            //允许T, mut T, &mut T
        }
    }

    let mut x1 = X {
        name: "asd".to_string(),
    };
    x1.t1();

    #[derive(Debug)]
    struct X {
        name: String,
    }
    impl X {
        fn t(self) {}
        fn t1(&self) {
            unsafe {
                (*(self as *const Self as *mut Self)).name = "a".to_string();
            }
        }
        fn t2(&mut self) {}
    }

    DBG!(x1);

    let r1 = 1;
    let r1p = &r1 as *const i32 as *mut i32;
    DBG!(r1); //1
    unsafe {
        *r1p = 2;
    }
    DBG!(r1); //2

    /// 类别 {const,mut}
    /// 类型 {T, 'a T, &T, &mut T, &'a T, *const T, *mut T }
    /// 变化如下
    /// T               mut T
    /// |                 |
    /// &T              &mut T
    /// |                 |
    /// *const T   <->  *mut T
    // 类别const 类型i32                             // 类别mut 类型i32
    let z = 1;
    let mut zm = 1;
    // 类别const 类型&i32                            // 类别mut 类型&mut i32
    let zr = &z;
    let zmr = &mut zm;
    // 类别const 类型*const i32                      // 类别mut 类型*mut i32
    let mut zp = &z as *const i32;
    let mut zmp = &mut zm as *mut i32;
    // 其中raw pointer可以相互转换
    // zp = zmp as *const i32;
    // zmp = zp as *mut i32;

    let trans = String::from("ddd");
    let trans2 = trans;
    // DBG!(trans);所有权已被转移

    let trb = String::from("ddd");
    let tf = &trb;
    let tf1 = tf;
    DBG!(tf); // 引用变量无所谓

    let tpb = String::from("ddd");
    let tpp = &tpb as *const String;
    let tpp1 = tpp;
    DBG!(tpp);

    #[derive(Debug, Copy, Clone)]
    struct Shit {
        age: u32,
    }
    let shi1 = Shit { age: 1 };
    let shi2 = shi1;
    DBG!(shi1); // 发生拷贝，原有变量未转移
                // let sll = [String::from("asd"),String::from("asd")];
                // let sll1 = sll;
                // DBG!(sll);// 虽然[]实现了copy+clone但是内部T未实现clone或者copy，内部变量出现转移，编译失败

    #[derive(Debug)]
    struct Shit1 {
        age: Cell<i32>,
    }

    let shi0 = Shit1 { age: Cell::new(1) };
    shi0.age.set(12);
    // shi0.age = 2;//内部不可变 值类别由外向内全覆盖，不可变类型其内部值也不可变
    DBG!(shi0);

    #[derive(Debug)]
    struct Shit2 {
        age: u32,
    }
    impl Shit2 {
        fn get_mut(&mut self) -> &mut u32 {
            &mut self.age
        }

        fn set_any_way(&self, age: u32) {
            unsafe {
                *(&self.age as *const u32 as *mut u32) = age;
            }
        }
    }

    let ssss = Shit2 { age: 32 };
    DBG!(ssss);
    ssss.set_any_way(11);
    DBG!(ssss);
    let value = Rc::new(RefCell::new(5));
    let rc = Rc::clone(&value);
    let rc1 = Rc::clone(&value);
    *rc.deref().borrow_mut() += 3;
    DBG!(value);
    *rc1.deref().borrow_mut() += 4;
    DBG!(value);

    struct MoveOut {
        name: String,
    }

    impl MoveOut {
        fn out(&self) -> MoveOut {
            MoveOut {
                name: self.name.clone(),
            }
        }

        fn out_mut(&mut self) -> MoveOut {
            MoveOut {
                name: replace(&mut self.name, "".to_string()),
            }
        }
    }

    let ipv6 = IP::IPV6;
    test_ip(&ipv6);
    DBG!(ipv6);
    let mut person1 = Person {
        name: "wang".to_string(),
        age: 1,
    };

    fn lambda<T>(op: Option<T>) -> Option<T>
    where
        T: Debug + std::ops::Add<i32, Output = T>,
    {
        match op {
            Some(mut any) => {
                any = any + 1;
                println!("match any here {:#?}", &any);
                return Some(any);
            }
            None => None,
        }
    }
    lambda(Some(1));

    let ap = 1;
    match ap {
        1 => println!("{}", 1),
        _ => println!("none matched"),
    }
    println!("{}", ap);

    let asd: &str = "sada";
    DBG!(test_slice_str(&asd, 1, 2));
    DBG!(test_slice_string(&asd, 1, 2));
    DBG!(test_slice_cstring(&asd, 1, 2));

    let vec1 = vec!["blue", "white"];
    let vec2 = vec![20, 30];
    let mut map: HashMap<_, _> = vec1.iter().zip(vec2.iter()).collect();
    map.insert(&"ad", &12);
    match &map {
        v => println!("{:?}", v),
    }
    // let string = test_input().unwrap_or("".to_string());
    // DBG!(string);
    DBG!(map);
    let mut string1 = String::from("ad");
    test_fn_move(string1);
    DBG!(ffa(100));

    // testCounter
    let x: _ = CusCounter::new().filter(|e| e > &1).sum::<u32>();
    DBG!(x);
    let s @ CusCounter { count } = CusCounter { count: 1 };
    DBG!(s);

    let str1 = String::from("asd".to_string());
    let str2 = &str1;
    let (ts, rc) = mpsc::channel();
    let handle = thread::spawn(move || {
        DBG!(str1);
        thread::sleep(Duration::from_secs(2));
        ts.send(str1).unwrap();
    });

    let mut mutex = Mutex::new(String::from("asd"));
    *mutex.lock().unwrap().deref_mut() = "asdasdad".to_string();
    DBG!(rc.recv().unwrap());


}

enum List {}
//定义类
#[derive(Debug)]
struct CusCounter {
    count: u32,
}

//定义类方法
impl CusCounter {
    pub fn new() -> CusCounter {
        CusCounter { count: 0 }
    }
}

//给类添加迭代特性
impl Iterator for CusCounter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;
        if self.count < 10 {
            Some(self.count)
        } else {
            None
        }
    }
}

fn fa(intro: u64) -> u64 {
    match intro {
        0 => 0,
        1 => 1,
        e => fa(e - 1) + fa(e - 2),
    }
}

fn ffa(intro: u64) -> u128 {
    let mut x = 0 as u128;
    let mut y = 1 as u128;
    let mut tmp: u128;
    for _ in 0..intro {
        tmp = x + &y;
        x = replace(&mut y, tmp);
    }
    x
}

fn test_fn_move(mut intro: String) {
    DBG!(intro);
    intro.push_str(&"ad".to_string());
    DBG!(intro);
}

fn test_input() -> std::io::Result<String> {
    let mut result = String::new();
    stdin().read_line(&mut result)?;
    Ok(result)
}

fn test_vec() {
    let mut vec1 = vec![1.0, 2.0, 3.0];
    let asd = "asd".to_string();
    let i = (1..2).start;
    let x = [1, 2][0];
}
